package com.geekbang.thinking.in.spring.dependency.injection;

import com.geekbang.thinking.in.spring.dependency.injection.annotation.InjectedUser;
import com.geekbang.thinking.in.spring.dependency.injection.annotation.MyAutowired;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.*;

/**
 * 注解驱动的依赖注入处理过程
 *
 */
// @Configuration
public class AnnotationDependencyInjectionResolutionDemo {

    @Autowired
    private User lazyUser;

    @Autowired
    private User user;  // 依赖查找（处理）
                        // DependencyDescriptor ->
                        // 必须（required = true）
                        // 实时注入（eager = true） +
                        // 通过类型（User.class）
                        // 字段名称（"user"）
                        // 是否是首要的（primary = "true"）

    @Autowired          // 集合类型依赖注入
    private Map<String, User> users;

    @MyAutowired
    private Optional<User> userOptional; // superUser

    @Inject
    private User injectUser;

    @InjectedUser
    private User myInjectedUser;

    @Bean(name = "injectedUserAnnotationBeanPostProcessor")
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        // 新注解 @InjectedUser + 原有注解
        Set<Class<? extends Annotation>> autowiredAnnotationTypes =
                new LinkedHashSet<>(Arrays.asList(Autowired.class, InjectedUser.class, Inject.class));
        beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
        return beanPostProcessor;
    }

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class (配置类) -> Spring Bean
        applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);

        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);

        String xmlResourcePath = "classpath:META-INF/dependency-lookup-context.xml";

        beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);

        // 启动应用上下文
        applicationContext.refresh();

        // 依赖查找 AnnotationDependencyFieldInjectionDemo Bean
        AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);

        System.out.println("user: " + demo.user);  // superUser
        System.out.println("users: " + demo.users);
        System.out.println("userOptional: " + demo.userOptional);
        System.out.println("lazyUser: " + demo.lazyUser);
        System.out.println("injectUser: " + demo.injectUser);

        System.out.println("myInjectedUser: " + demo.myInjectedUser);

        // 显示关闭上下文
        applicationContext.close();
    }

}
